package org.rain.core.aspect;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.stream.Collectors;

/**
 * created by yangtong on 2025/4/12 09:15:31
 * <br/>
 * 日志切面
 */
@Aspect
@Component
public class LogAspect {

    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);

    @Pointcut("@annotation(org.rain.common.anno.AutoLog)")
    public void logPointcut() {
    }

    @Around("logPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 方法名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String classMethod = signature.getDeclaringTypeName() + "." + signature.getName();

        // 入参
        Object[] args = joinPoint.getArgs();
        String params = Arrays.stream(args)
                .map(arg -> {
                    try {
                        return new ObjectMapper().writeValueAsString(arg);
                    } catch (JsonProcessingException e) {
                        return String.valueOf(arg);
                    }
                })
                .collect(Collectors.joining(", "));

        Object result = null;

        long startTime = System.currentTimeMillis();
        try {
            result = joinPoint.proceed();
            return result;
        } finally {
            long duration = System.currentTimeMillis() - startTime;

            //记录日志
            if (result != null && result.toString().length() > 1024) {
                result = result.toString().substring(0, 1024);
            }
            log.info("方法名称：【{}】，入参：【{}】，返回结果：【{}】，耗时：【{}】", classMethod, params, result, duration);
        }
    }

}
